package com.songyang.yougnsql.core.data.logger;

import com.songyang.yougnsql.common.ErrorMsg;
import com.songyang.yougnsql.common.ExceptionHandler;
import com.songyang.yougnsql.common.YoungSQLException;
import com.songyang.yougnsql.core.utils.ByteUtils;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

public interface Logger {
    static boolean isFirst = false;

    /**
     * 打开一个日志文件，如果传入的日志文件路径不存在则会创建新的
     *
     * @param path 日志文件路径
     * @return Logger
     * @throws YoungSQLException 异常
     */
    static Logger open(String path) throws YoungSQLException {
        File file = new File(path + File.separator + "YoungSQL" + LoggerImpl.LOG_SUFFIX);
        boolean isFirst = file.exists();
        try {
            if (!file.exists() && !create(file.getPath())) {
                throw new YoungSQLException(ErrorMsg.FILE_CREATE_FAILED_EXCEPTION);
            }
            RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw");
            FileChannel fileChannel = randomAccessFile.getChannel();
            return isFirst ? new LoggerImpl(randomAccessFile, fileChannel, 0) : new LoggerImpl(randomAccessFile, fileChannel);
        } catch (YoungSQLException | FileNotFoundException e) {
            ExceptionHandler.handler(e);
        }
        throw new YoungSQLException(ErrorMsg.CREATE_PAGE_CACHE_FAILED);
    }

    /**
     * 当日志文件不存在的时候，先创建一个日志文件
     *
     * @param path 日志文件的路径
     * @return 创建结果
     */
    static boolean create(String path) {
        File file = new File(path);
        try {
            if (!file.createNewFile()) {
                throw new YoungSQLException(ErrorMsg.FILE_CREATE_FAILED_EXCEPTION);
            }
            if (!file.canRead() || !file.canWrite()) {
                throw new YoungSQLException(ErrorMsg.FILE_CANNOT_RW_EXCEPTION);
            }
            RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw");
            FileChannel fileChannel = randomAccessFile.getChannel();
            ByteBuffer buf = ByteBuffer.wrap(ByteUtils.int2Byte(0));
            fileChannel.position(0);
            fileChannel.write(buf);
            fileChannel.force(false);
            fileChannel.close();
            randomAccessFile.close();
            return true;
        } catch (IOException | YoungSQLException e) {
            ExceptionHandler.handler(e);
            return false;
        }
    }


    void insertLog(byte[] data);

    void truncate(long x) throws Exception;

    //    byte[] nextLogData();
    byte[] nextLog();

    void rewind();

    void close();
}
